//
// Templet.h
//
// $Id: //base/include/Templet.h
//
// Library: base
// Package: base
// Module : Templet
// Author :	Jelin,doitsjz@163.com
// Date	  :	10/30/2012
// 
// Definition of the Templet class.
//
// Copyright (c) 2012-2012, iGuard.
//
#include "RTSPSession.h"
#include "Poco/UUIDGenerator.h"
#include "Poco/UUID.h"
#include "Poco/NumberFormatter.h"
#include "Poco/Timestamp.h"

#include <sstream>

using Poco::UUIDGenerator;
using Poco::UUID;
using Poco::NumberFormatter;
using Poco::Int64;
using Poco::UInt64;
using Poco::Timestamp;

RTSPSession::RTSPSession()
{
	m_cseqID	= 1;
	m_sessionID = "";
	//m_pRequest = new RTSPRequest;
	//m_pReply   = new RTSPResponse;
}

RTSPSession::~RTSPSession()
{
	//if (m_pRequest)
	//	delete m_pRequest;
	//if (m_pReply)
	//	delete m_pReply;
}
int RTSPSession::getCSeqID()
{
	return m_cseqID++;
};
void RTSPSession::addCSeq(int seqid,string method)
{
	m_CSeqMap.insert(pair<int,string>(seqid,method));
}
bool RTSPSession::findCSeq(int seqid,string& method)
{
	m_CSeqIt = m_CSeqMap.find(seqid);
	if (m_CSeqIt != m_CSeqMap.end())
	{
		method = m_CSeqIt->second;
		return true;			
	}
	return false;
}
std::string RTSPSession::generateUUID()
{
	UUIDGenerator& gen = UUIDGenerator::defaultGenerator();
	UUID uuid = gen.createRandom();
	return uuid.toString();
	//Timestamp tt;
	//Timestamp::UtcTimeVal tv = tt.utcTime();

	//return NumberFormatter::format(tv);
}

int RTSPSession::handleMessage0(const char* buff,int iLen,pj_size_t* iLeft)
{
	//RTSPMessage* pRtspMessage = NULL;
	//convert buff into RTSPMessage(RTSPRequest or RTSPResponse)
	//iMessageLen - a whole rtsp message length
	//iPos- current position for finding 
	int iMessageLen = 0,iPos=0;
	//nLFPos- CRLF position,nCLPos- Content-Length position
	size_t nLFPos,nCLPos;
	std::string strBuf(buff,iLen);
	
	while ((nLFPos = strBuf.find("\r\n\r\n",iPos))!=string::npos)
	{
		iMessageLen = nLFPos + 4 - iPos;//rtsp message length seprate by CRLFCRLF
		//find content for rtsp message
		if ((nCLPos = strBuf.find(RTSPMessage::ContentLength.c_str(),iPos))!=string::npos)
		{
			//one more rtsp message arrvied ,Content_Length may be later message
			if (nCLPos < nLFPos)//ContentLength be in first message
			{
				//get body length
				int bodyLen = atoi(buff+nCLPos+RTSPMessage::ContentLength.length()+1);
				if (bodyLen >iLen-iMessageLen)	//continue recv,don't parse
				{
					*iLeft = iLen;
				}
				else// if (bodyLen <= iLen-iReadLen)
				{
					iMessageLen += bodyLen;
				}
			}
			//if (found2>found) ContentLength after first rtsp message
			//so we have whole rtsp message,can parse this message and goon
		}

		std::string strMessage(buff+iPos,iMessageLen);
		iPos += iMessageLen;

		std::istringstream istr(strMessage);
		bool bRequest = true;;
		if (strMessage.substr(0,RTSPMessage::RTSP_1_0.length()) == RTSPMessage::RTSP_1_0)
		{
				//m_pReply = new RTSPResponse;//RTSPResponse
				m_Reply.read(istr);
				bRequest = false;;
		}
		else
		{
			//m_pRequest = new RTSPRequest;//RTSPRequest
			m_Request.read(istr);
		}
		//call subclass <handleMessage>
		if (bRequest)
		{
			handleMessage(m_Request);
			m_Request.clear();
		}
		else
		{
			handleMessage(m_Reply);
			m_Reply.clear();
		}
	}

	//the request or response not whole,and remain iLen data 
	if (iPos != iLen)
		*iLeft = iLen;

	return PJ_TRUE;
}

int RTSPSession::makeOptionsRequest(std::string& req)
{
	RTSPRequest request(RTSPRequest::OPTIONS, "*");
	int seqid = getCSeqID();

	request.setCSeq(seqid);
	request.setDate();
	request.setUserAgent();
	std::ostringstream ostr;
	request.write(ostr);
	req = ostr.str();

	addCSeq(seqid,RTSPRequest::OPTIONS);

	return 0;
}
int RTSPSession::makeOptionsReply(RTSPRequest& request,std::string& rep)
{
	RTSPResponse reply;
	reply.setCSeq(request.getCSeq());
	reply.setDate();
	reply.setUserAgent();
	reply.setPublic();
	std::ostringstream ostr;
	reply.write(ostr);
	rep = ostr.str();

	return 0;
}
